use std::num::ParseIntError;
use std::str::FromStr;
use std::thread;
use std::time::{Duration, UNIX_EPOCH};

use error_chain::error_chain;
use reqwest::blocking::Client;
use reqwest::header::ToStrError;
use reqwest::StatusCode;

error_chain! {
    foreign_links {
        Io(std::io::Error);
        Time(std::time::SystemTimeError);
        Reqwest(reqwest::Error);
        ToStr(ToStrError);
        ParseError(ParseIntError);
    }
}

fn main() -> Result<()> {
    loop {
        let url = "https://api.github.com/users/rust-lang-nursery";
        let client = Client::new();
        let response = client.get(url).send()?;

        let rate_limit = usize::from_str(response.headers().get("X-RateLimit-Limit").ok_or("response doesn't include the expected X-RateLimit-Limit header")?.to_str()?)?;

        let rate_remaining = usize::from_str(response.headers().get("X-RateLimit-Remaining").ok_or("response doesn't include the expected X-RateLimit-Remaining header")?.to_str()?)?;

        let rate_reset_at = u64::from_str(response.headers().get("X-RateLimit-Reset").ok_or("response doesn't include the expected X-RateLimit-Reset header")?.to_str()?)?;

        let rate_reset_within = Duration::from_secs(rate_reset_at) - UNIX_EPOCH.elapsed()?;

        if response.status() == StatusCode::FORBIDDEN && rate_remaining == 0 {
            println!("Sleeping for {} seconds.", rate_reset_within.as_secs());
            thread::sleep(rate_reset_within);
            return main();
        } else {
            println!(
                "Rate limit is currently {}/{}, the reset of this limit will be within {}",
                rate_remaining,
                rate_limit,
                rate_reset_within.as_secs()
            );
            break;
        }
    }
    Ok(())
}
